<?php

namespace App\Http\Controllers\WeChat;

use App\Http\Controllers\Controller;
use App\Models\App\AppUser;
use App\Models\Common\ApiResponse;
use App\Models\ParkingLot\Lane;
use App\Models\ParkingLot\ParkingLot;
use App\Models\ParkingLot\ParkingLotArea;
use App\Models\Setting\Setting;
use App\Models\WeChat\WMP;
use Carbon\Carbon;
use Illuminate\Http\Request;

class WmpController extends Controller
{
    public function login(Request $request): array
    {
        $data = $request->post();

        if (!$invoke = \Arr::get($data, 'invoke')) {
            ApiResponse::return('小程序类型必填', '', ApiResponse::CODE_INVALID_ARGUMENT);
        }
        if (!$code = \Arr::get($data, 'code')) {
            ApiResponse::return('授权code必填', '', ApiResponse::CODE_INVALID_ARGUMENT);
        }

        $app = WMP::getInstance($invoke);

        $err = '';
        try {
            // 获取手机号
            $phoneInfo = $app->auth->httpPostJson('https://api.weixin.qq.com/wxa/business/getuserphonenumber', ['code' => $code]);
            if (\Arr::get($phoneInfo, 'errcode')) {
                $err = \Arr::get($phoneInfo, 'errmsg', 'code已失效或错误');
                throw new \InvalidArgumentException($err);
            }
//                  {"errcode":0,"errmsg":"ok","phone_info":{"phoneNumber":"13105899999","purePhoneNumber":"13105899999","countryCode":"86","watermark":{"timestamp":1665458170,"appid":"wxfa837d70b6dc0048"}}}

            if (!$phone = \Arr::get($phoneInfo, 'phone_info.purePhoneNumber')) {
                $err = '获取手机号码失败';
                throw new \InvalidArgumentException($err);
            }

            $pattern = "/(\d{3})\d{4}(\d{4})/";
            $replacement = '$1****$2';
            $name = preg_replace($pattern, $replacement, $phone); // 隐藏手机号中间4位
            if ($appUser = AppUser::firstOrCreate(['phone' => $phone], [
                'name' => $name,
                'phone' => $phone,
//                'password' => bcrypt('123456')
            ])) {
                $appUser->login_at = now();
                $appUser->save();

                $token = auth('app')->tokenById($appUser->id);

                return ApiResponse::return('', ['token' => $token]);
            }

        } catch (\Throwable $exception) {
            throw new \InvalidArgumentException('小程序授权失败 ' . $err . $exception->getMessage());
        }

        return ApiResponse::return('登录失败', '', ApiResponse::RESP_CODE_FAILURE);
    }

    public function openid(Request $request): array
    {
        $data = $request->post();

        if (!$invoke = \Arr::get($data, 'invoke')) {
            ApiResponse::return('小程序类型必填', '', ApiResponse::CODE_INVALID_ARGUMENT);
        }
        if (!$code = \Arr::get($data, 'code')) {
            ApiResponse::return('授权code必填', '', ApiResponse::CODE_INVALID_ARGUMENT);
        }

        $app = WMP::getInstance($invoke);

        try {
            $response = $app->auth->session($code);
            if ($openid = \Arr::get($response, 'openid')) {
                if ($appUser = app_user()) {
                    $appUser->wmp_openid = $openid;
                    $appUser->save();
                }
                return ApiResponse::return('', ['openid' => $openid]);
            }
            \Log::warning('小程序openid授权失败', ['data' => $data, 'res' => $response]);
            throw new \InvalidArgumentException('小程序授权失败 ');
        } catch (\Throwable $exception) {
            \Log::warning('小程序openid授权失败_', ['data' => $data, 'res' => $response]);
            throw new \InvalidArgumentException('小程序授权失败_' . $exception->getMessage());
        }
    }

    public function schemeUrl(Request $request): array
    {
        $data = $request->post();

        if (!$invoke = \Arr::get($data, 'invoke')) {
            ApiResponse::return('小程序类型必填', '', ApiResponse::CODE_INVALID_ARGUMENT);
        }

        $path = \Arr::get($data, 'path', '');
        $query = \Arr::get($data, 'query', '');

        $app = WMP::getInstance($invoke);

        try {
            $response = $app->auth->httpPostJson('https://api.weixin.qq.com/wxa/generatescheme', [
                'jump_wxa' => [
                    'path' => $path,
                    'query' => $query,
//                    'env_version' => 'release' //release正式版，trial体验版，develop开发版 仅在微信外打开时生效
                ],
                'is_expire' => true,
                'expire_type' => 1,
                'expire_interval' => 1
            ]);
            if ($link = \Arr::get($response, 'openlink')) {
                return ApiResponse::return('', $link);
            } else {
                \Log::info('获取小程序scheme码失败', $response);
                if (is_array($response)) {
                    \Log::info('获取小程序码失败', $response);
                    throw new \InvalidArgumentException('获取小程序码失败:'.\Arr::get($response, 'errmsg'));
                } else {
                    throw new \InvalidArgumentException('获取小程序码失败');
                }
            }
        } catch (\Throwable $exception) {
            throw new \InvalidArgumentException('小程序授权失败_' . $exception->getMessage());
        }
    }

    public function qrCode(Request $request): array
    {
        $data = $request->post();

        if (!$invoke = \Arr::get($data, 'invoke')) {
            ApiResponse::return('小程序类型必填', '', ApiResponse::CODE_INVALID_ARGUMENT);
        }

        $type = \Arr::get($data, 'type');
        $query = \Arr::get($data, 'query');
        $width = \Arr::get($data, 'width') ?: 340;
        $refresh = \Arr::get($data, 'refresh');
        $path = $scene = $url = '';
        $optional = [];

        switch ($invoke) {
            case Setting::CATEGORY_WMP_APP:
                $parkingLotID = getParkingLotID();
                if (!$parkingLot = ParkingLot::find($parkingLotID)) {
                    ApiResponse::return('未查询到车场信息', '', ApiResponse::CODE_INVALID_ARGUMENT);
                }
                switch ($type) {
                    case 'index': // 首页
                        $path = 'pages/index/index?parking_lot_id=' . $parkingLotID . '&parking_lot_name=' . $parkingLot->name;
                        $optional = [
                            'width' => $width,
//                            'env_version' => 'trial' // release正式版、trial体验版
                        ];
                        $setting = Setting::where(['parking_lot_id' => $parkingLotID, 'category' => Setting::CATEGORY_WMP_QR_CODE, 'key' => Setting::CATEGORY_WMP_APP_INDEX])->first();

                        $wmpQrCode = optional($setting)->value;
                        if (!$wmpQrCode) {
                            $refresh = true;
                        } else {
                            $url = $wmpQrCode;
                        }
                        if ($refresh) {
                            $url = self::wmpAppCode($invoke, $path, $optional, $parkingLotID);

                            // 删除原二维码
//                            if ($wmpQrCode) {
//                                $filePath = public_path($wmpQrCode);
//                                if (file_exists($filePath)) {
//                                    @unlink($filePath);
//                                }
//                            }

                            Setting::updateOrCreate([
                                'category' => Setting::CATEGORY_WMP_QR_CODE,
                                'key' => Setting::CATEGORY_WMP_APP_INDEX,
                                'parking_lot_id' => $parkingLotID,
                            ], [
                                'value' => $url
                            ]);
                        }
                        break;
                    case 'park_export': // 预付码
                        $path = 'pages/index/index?parking_lot_id=' . $parkingLotID . '&parking_lot_name=' . $parkingLot->name;
                        $optional = [
                            'width' => $width,
//                            'env_version' => 'trial' // release正式版、trial体验版
                        ];
                        $setting = Setting::where(['parking_lot_id' => $parkingLotID, 'category' => Setting::CATEGORY_WMP_QR_CODE, 'key' => Setting::CATEGORY_WMP_APP_OUT])->first();

                        $wmpQrCode = optional($setting)->value;
                        if (!$wmpQrCode) {
                            $refresh = true;
                        } else {
                            $url = $wmpQrCode;
                        }
                        if ($refresh) {
                            $url = self::wmpAppCode($invoke, $path, $optional, $parkingLotID);

                            Setting::updateOrCreate([
                                'category' => Setting::CATEGORY_WMP_QR_CODE,
                                'key' => Setting::CATEGORY_WMP_APP_INDEX,
                                'parking_lot_id' => $parkingLotID,
                            ], [
                                'value' => $url
                            ]);
                        }

                        break;
                    case 'area_export': // 区域预付码
                        if (!$id = $query) {
                            throw new \InvalidArgumentException('区域ID不可为空');
                        }
                        if (!$area = ParkingLotArea::where('parking_lot_id', $parkingLotID)->where('id', $id)->first()) {
                            throw new \InvalidArgumentException('未查询到区域信息');
                        }
                        if (ParkingLotArea::CATEGORY_OUT !== $area->category) {
                            throw new \InvalidArgumentException('非外场区域');
                        }
                        $path = 'pages/index/index?parking_lot_id=' . $parkingLotID . '&area_id=' . $area->id . '&parking_lot_name=' . $parkingLot->name;
                        $optional = [
                            'width' => $width,
//                            'env_version' => 'trial' // release正式版、trial体验版
                        ];
                        $wmpCode = $area->wmp_code;
                        $wmpQrCode = \Arr::get($wmpCode, 'entrance');
                        if (!$wmpQrCode) {
                            $refresh = true;
                        } else {
                            $url = $wmpQrCode;
                        }
                        if ($refresh) {
                            $url = self::wmpAppCode($invoke, $path, $optional, $parkingLotID);
                            $wmpCode['entrance'] = $url;
                            $area->wmp_code = $wmpCode;
                            $area->save();
                        }

                        break;
                    case 'lane_export': // 车道出口码
                        if (!$id = $query) {
                            throw new \InvalidArgumentException('车道ID不可为空');
                        }
                        if (!$lane = Lane::where('parking_lot_id', $parkingLotID)->where('id', $id)->first()) {
                            throw new \InvalidArgumentException('未查询到车道信息');
                        }
                        $path = 'pages/index/index?parking_lot_id='.$parkingLotID.'&&lane_id='.$lane->id . '&parking_lot_name=' . $parkingLot->name;
                        $optional = [
                            'width' => $width,
//                            'env_version' => 'trial' // release正式版、trial体验版
                        ];
                        $wmpCode = $lane->wmp_code;
                        $wmpQrCode = \Arr::get($wmpCode, 'export');
                        if (!$wmpQrCode) {
                            $refresh = true;
                        } else {
                            $url = $wmpQrCode;
                        }
                        if ($refresh) {
                            $url = self::wmpAppCode($invoke, $path, $optional, $parkingLotID);
                            $wmpCode['export'] = $url;
                            $lane->wmp_code = $wmpCode;
                            $lane->save();
                        }
                        break;
                    case 'lane_entrance': // 车道入口码
                        if (!$id = $query) {
                            throw new \InvalidArgumentException('车道ID不可为空');
                        }
                        if (!$lane = Lane::where('parking_lot_id', $parkingLotID)->where('id', $id)->first()) {
                            throw new \InvalidArgumentException('未查询到车道信息');
                        }
                        $path = 'pages/lane/entrance?lane_id=' . $lane->id . '&&parking_lot_id=' . $parkingLotID;
                        $optional = [
                            'width' => $width,
//                            'env_version' => 'trial' // release正式版、trial体验版
                        ];
                        $wmpCode = $lane->wmp_code;
                        $wmpQrCode = \Arr::get($wmpCode, 'entrance');
                        if (!$wmpQrCode) {
                            $refresh = true;
                        } else {
                            $url = $wmpQrCode;
                        }
                        if ($refresh) {
                            $url = self::wmpAppCode($invoke, $path, $optional, $parkingLotID);
                            $wmpCode['entrance'] = $url;
                            $lane->wmp_code = $wmpCode;
                            $lane->save();
                        }

                        break;
                    default:
                        throw new \InvalidArgumentException('路径类型错误');
                }
                break;
            case Setting::CATEGORY_WMP_ADMIN:
                $parkingLotID = getParkingLotID();
                if (!$parkingLot = ParkingLot::find($parkingLotID)) {
                    ApiResponse::return('未查询到车场信息', '', ApiResponse::CODE_INVALID_ARGUMENT);
                }
                switch ($type) {
                    case 'index': // 首页
                        $path = 'pages/index/index?parking_lot_id=' . $parkingLotID;
                        $optional = [
                            'width' => $width,
                        ];
                        $setting = Setting::where(['parking_lot_id' => $parkingLotID, 'category' => Setting::CATEGORY_WMP_QR_CODE, 'key' => Setting::CATEGORY_WMP_ADMIN_INDEX])->first();

                        $wmpQrCode = optional($setting)->value;
                        if (!$wmpQrCode) {
                            $refresh = true;
                        } else {
                            $url = $wmpQrCode;
                        }
                        if ($refresh) {
                            $url = self::wmpAppCode($invoke, $path, $optional);

                            Setting::updateOrCreate([
                                'category' => Setting::CATEGORY_WMP_QR_CODE,
                                'key' => Setting::CATEGORY_WMP_ADMIN_INDEX,
                                'parking_lot_id' => $parkingLotID,
                            ], [
                                'value' => $url
                            ]);
                        }
                        break;
                }
                break;
            case Setting::CATEGORY_WMP_MERCHANT:
                $parkingLotID = getParkingLotID();
                if (!$parkingLot = ParkingLot::find($parkingLotID)) {
                    ApiResponse::return('未查询到车场信息', '', ApiResponse::CODE_INVALID_ARGUMENT);
                }
                switch ($type) {
                    case 'index': // 首页
                        $path = 'pages/index/index?parking_lot_id=' . $parkingLotID;
                        $optional = [
                            'width' => $width,
                        ];
                        $setting = Setting::where(['parking_lot_id' => $parkingLotID, 'category' => Setting::CATEGORY_WMP_QR_CODE, 'key' => Setting::CATEGORY_WMP_MERCHANT_INDEX])->first();

                        $wmpQrCode = optional($setting)->value;
                        if (!$wmpQrCode) {
                            $refresh = true;
                        } else {
                            $url = $wmpQrCode;
                        }
                        if ($refresh) {
                            $url = self::wmpAppCode($invoke, $path, $optional);

                            Setting::updateOrCreate([
                                'category' => Setting::CATEGORY_WMP_QR_CODE,
                                'key' => Setting::CATEGORY_WMP_MERCHANT_INDEX,
                                'parking_lot_id' => $parkingLotID,
                            ], [
                                'value' => $url
                            ]);
                        }
                        break;
                }
                break;
            default:
                ApiResponse::return('小程序类型错误', '', ApiResponse::CODE_INVALID_ARGUMENT);
        }

        $url && $url = config('app.url').'/'.$url;
        return ApiResponse::return('', $url);
    }

    private function wmpAppCode($invoke, $path, $optional, $parkingLotID = '')
    {
        if (!$path) {
            throw new \InvalidArgumentException('页面路径为空');
        }

        try {
            $app = WMP::getInstance($invoke);
//            \Log::info('获取小程序码：'.$path, $optional);

            $response = $app->app_code->get($path, $optional); // 数量限制100000

//            $scene = format_uuid($parkingLotID, false);
//            $optional = [
//                'page'  => 'pages/index/index',
//                'width' => 340,
//            ];
//            $response = $app->app_code->getUnlimit($scene, $optional);

            if ($response instanceof \EasyWeChat\Kernel\Http\StreamResponse) {
                $contents = $response->getBody()->getContents();

                $parkingLotID = $parkingLotID ? (format_uuid($parkingLotID, false) . '/') : '';
                $imgKey = str_replace('.', '', uniqid("/wmpQrCode/{$parkingLotID}", true)).'.jpg';

//                $filename = $response->saveAs(storage_path($dir), $imgKey);
                $disk = \Storage::disk('public');
                if ($disk->put($imgKey, $contents)) {
                    if ($disk->exists($imgKey)) {
                        return 'storage' . $imgKey;
                    }
                }
                throw new \InvalidArgumentException('保存图片失败');
            }
            else {
                if (is_array($response)) {
                    \Log::info('获取小程序码失败', $response);
                    throw new \InvalidArgumentException('获取小程序码失败:'.\Arr::get($response, 'errmsg'));
                } else {
                    throw new \InvalidArgumentException('获取小程序码失败');
                }
            }
        } catch (\Exception $exception) {
            throw new \InvalidArgumentException('获取小程序码失败' . $exception->getMessage());
        }
    }

    public function wmpAdv(Request $request): array
    {
        $data = $request->post();

        if (!$invoke = \Arr::get($data, 'invoke')) {
            ApiResponse::return('小程序类型必填', '', ApiResponse::CODE_INVALID_ARGUMENT);
        }

        $data = [];
        if ($settings = Setting::where('category', $invoke)->pluck('value', 'key')->toArray()) {
            switch ($invoke) {
                case Setting::CATEGORY_WMP_APP:
                    $unit_id = \Arr::get($settings, 'bottom_adv_unit_id', '');
                    $beginTime = \Arr::get($settings, 'bottom_adv_time_begin');
                    $endTime = \Arr::get($settings, 'bottom_adv_time_end');
                    $bottom = [
                        'unit_id' => self::checkUnitId($unit_id, $beginTime, $endTime),
                        'url' => \Arr::get($settings, 'bottom_adv_url', ''),
                        'link' => \Arr::get($settings, 'bottom_adv_link', ''),
                    ];
                    $data = [
                      'bottom' => $bottom
                    ];
                    break;
            }
        }

        return ApiResponse::return('', $data);
    }

    private function checkUnitId($unit_id, $start_time, $end_time)
    {
        if ($start_time && $end_time) {
            $startAt = Carbon::parse($start_time);
            $endAt = Carbon::parse($end_time);
            if ($startAt <= now() && $endAt > now()) {
                $unit_id = '';
            }
        }
        return $unit_id;
    }
}
